/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package share;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author mire
 */
public class SocketCommunicator implements Communicator {

    private Socket s;
    private OutputStream os;
    private InputStream is;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;
    private boolean closed = true;
    //private byte control = 0x1D; ^] xexe
    private byte control = '#';
    private boolean controlRead = false;
    private boolean controlWrite = false;

    public SocketCommunicator(Socket s) {
        this.s = s;
    }

    public SocketCommunicator(Socket s, int waitForAnswerTime) throws SocketException {
        this.s = s;
        this.s.setSoTimeout(waitForAnswerTime * 1000);
    }

    public String getAddress() {
        return s.getInetAddress().getHostAddress();
    }

    public String getLocalAddress() {
        return s.getLocalAddress().getHostAddress();
    }

    public int getPort() {
        return s.getPort();
    }

    @Override
    public boolean open() throws IOException {
        if (!closed) {
            return true;
        }

        os = s.getOutputStream();
//        bos = new BufferedOutputStream(os);
        oos = new ObjectOutputStream(os);

        is = s.getInputStream();
//        bis = new BufferedInputStream(is);
        ois = new ObjectInputStream(is);

        closed = false;

        return true;
    }

    @Override
    public boolean close() throws IOException {
        if (closed) {
            return true;
        }


        os.close();
//        bos.close();
        oos.close();
        is.close();
//        bis.close();
        ois.close();
				s.close();

        closed = true;

        return true;
    }

    public boolean readControlBits() throws IOException {
        boolean good = false;
        byte readByte = ois.readByte();
        if (readByte == control) {
            good = true;
        }
        controlRead = true;
        return good;
    }

    public void writeControlBits() throws IOException {
        oos.writeByte(control);
        oos.flush();
        controlWrite = true;
    }

    @Override
    public Object readObject() throws IOException, ClassNotFoundException {
        if (!controlRead) {
            if(!readControlBits())
                throw new IOException("Control bits failed!");
        }
        return ois.readObject();
    }

    @Override
    public void writeObject(Object o) throws IOException {
        if (!controlWrite) {
            writeControlBits();
        }
        oos.writeObject(o);
        oos.flush();
    }

    @Override
    public String readString() throws IOException {
        String str = null;
        try {
            str = (String) ois.readObject();
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(FileCommunicator.class.getName()).log(Level.SEVERE, null, ex);
        }
        return str;
    }

    @Override
    public void writeString(String str) throws IOException {
        oos.writeObject(str);
        oos.flush();
    }

    @Override
    public int readInt() throws IOException {
        return ois.readInt();
    }

    @Override
    public void writeInt(int i) throws IOException {
        oos.writeInt(i);
        oos.flush();
    }

    public boolean isClosed() {
        return closed;
    }
}
